/**********************************************************************************
// DemoCollision
// 
// Creation:	30 Apr 2011
// Updated:		02 Apr 2011
// Compiler:	Visual Studio 2011
//
// Notes:		Test the collision detection using sprite bounding boxes
//
**********************************************************************************/

#define WIN32_LEAN_AND_MEAN  // just say no to MFC

#include "Resources.h"
#include "Anabele.h"	

/**********************************************************************************/
/*                          DemoCollision Class                                   */
/**********************************************************************************/

class CollisionDemo: public D3DGame
{
private:
	Sprite * demobox;
	Sprite * demobar;
	
	SceneManager scene;
	Input input;

	bool keyboardOn;
	bool mouseOn;
	bool xbox360On;

	Sprite * circle;
	Circle * circleBB;

	Sprite * plane;
	Sprite * planeRed;
	Poly * planeBB;

	float lastx, lasty;
	float scaling;
	float rotation;

	char text[256];
	bool viewBB;

public:
	CollisionDemo();

	void Restart();

	void GameInit();
	void GameLogic();
	void GameDraw();
	void GameShutdown();
	void UnloadResources();
	void LoadResources();
};

/**********************************************************************************/

CollisionDemo::CollisionDemo()
{
	viewBB     = false;
	keyboardOn = false;
	mouseOn    = false;
	xbox360On = false;
}

/**********************************************************************************/

void CollisionDemo::Restart()
{
	UnloadResources();

	scene.UnRegisterMoving(*planeBB);
	delete planeBB;

	lastx = GetWindowWidth()/2.0f;
	lasty = GetWindowHeight()/2.0f;
	scaling = 1.0f;
	rotation = 0.0f;

	Point vlist[22] = 
	{ 
		Point(0,-155), Point(12,-135), Point(16,-65), Point(169,-63),
		Point(179,-47), Point(165,-21), Point(24,17), Point(13,37),
		Point(9,89), Point(60,109), Point(60,126), Point(0,145),
		Point(-60,126), Point(-60,109), Point(-9,89), Point(-13,37),
		Point(-24,17), Point(-165,-19), Point(-179,-47), Point(-169,-62),
		Point(-16,-65), Point(-12,-135) 
	};

	planeBB = new Poly(vlist, 22);
	planeBB->MoveTo(lastx, lasty);

	scene.RegisterMoving (*planeBB);

	LoadResources();
}

/**********************************************************************************/

void CollisionDemo::GameInit()
{

	input.Initialize();

	keyboardOn = input.InitializeKeyboard();
	mouseOn    = input.InitializeMouse();
	xbox360On  = input.InitializeXbox360();

	lastx = GetWindowWidth()/2.0f;
	lasty = GetWindowHeight()/2.0f;
	scaling = 1.0f;
	rotation = 0.0f;

	circleBB = new Circle(215.0f);
	circleBB->MoveTo(lastx, lasty);
	
	Point vlist[22] = 
	{ 
		Point(0,-155), Point(12,-135), Point(16,-65), Point(169,-63),
		Point(179,-47), Point(165,-21), Point(24,17), Point(13,37),
		Point(9,89), Point(60,109), Point(60,126), Point(0,145),
		Point(-60,126), Point(-60,109), Point(-9,89), Point(-13,37),
		Point(-24,17), Point(-165,-19), Point(-179,-47), Point(-169,-62),
		Point(-16,-65), Point(-12,-135) 
	};

	planeBB = new Poly(vlist, 22);
	planeBB->MoveTo(lastx, lasty);

	scene.RegisterStatic(*circleBB);
	scene.RegisterMoving (*planeBB);

	LoadResources();
}

/**********************************************************************************/

void CollisionDemo::LoadResources()
{
	demobox = new Sprite("Resources/demoBox.png");
	demobox->MoveTo(155, 100);
	
	demobar = new Sprite("Resources/demoBar.png");
	demobar->MoveTo(GetWindowWidth()/2.0f, GetWindowHeight()-30.0f);

	circle = new Sprite("Resources/circle.png");
	circle->MoveTo(GetWindowWidth()/2.0f, GetWindowHeight()/2.0f);
	circle->boundingbox = circleBB;
	

	planeRed = new Sprite("Resources/airplaneRed.png");

	plane = new Sprite("Resources/airplane.png");
	plane->MoveTo(lastx, lasty);
	plane->scalingX = scaling;
	plane->scalingY = scaling;
	plane->rotation = rotation;
	plane->boundingbox = planeBB;
}

/**********************************************************************************/

void CollisionDemo::UnloadResources()
{
	lastx = plane->x;
	lasty = plane->y;
	scaling = plane->scalingX;
	rotation = plane->rotation;	

	if (demobar) delete demobar;
	if (demobox) delete demobox;
	if (circle) delete circle;
	if (plane) delete plane;
	if (planeRed) delete planeRed;
}

/**********************************************************************************/

void CollisionDemo::GameShutdown()
{
	if (circleBB) delete circleBB;
	if (planeBB) delete planeBB;

	UnloadResources();
}


/**********************************************************************************/

void CollisionDemo::GameLogic()
{
	// reset bounding box colors
	circle->boundingbox->color = Color(255,255,255);
	plane->boundingbox->color = Color(255,255,255);

	// Quits by pressing ESC
	EndsOnEscape();

	// ==== Keyboard input ====
	if (keyboardOn)
	{
		// Update keyboard state
		input.GetKeyboardState();

		// Restart Game (R)
		if (input.KeyPressed(DIK_R))
		{
			Restart();
		}

		// Enable Bounding Box (E)
		if (input.KeyPressed(DIK_E))
			viewBB = true;

		// Disable Bounding Box (D)
		if (input.KeyPressed(DIK_D))
			viewBB = false;

		// Scale (A and S)
		if (input.KeyPressed(DIK_A)) // scale up
			plane->Scale(1.1f, 1.1f);
		if (input.KeyPressed(DIK_S)) // scale down
			plane->Scale(0.9f, 0.9f);

		// Rotate (Z and X)
		if (input.KeyPressed(DIK_Z)) // rotate left
			plane->Rotate(-5);
		if (input.KeyPressed(DIK_X)) // rotate right
			plane->Rotate(5);

		// Translate 
		// (Right, Left, Up and Down)
		if (input.KeyPressed(DIK_RIGHT)) // translate right
			plane->Translate(10,0);
		if (input.KeyPressed(DIK_LEFT))  // translate left
			plane->Translate(-10,0);    
		if (input.KeyPressed(DIK_UP))    // translate up
			plane->Translate(0,-10); 
		if (input.KeyPressed(DIK_DOWN))  // translate down
			plane->Translate(0,10);
	}


	// ==== Mouse input ====
	if (mouseOn)
	{
		// Update mouse state
		input.GetMouseState();

		// Translate (mouse movement)
		plane->Translate(input.MouseAxis(MouseAxisX)*2.0f, input.MouseAxis(MouseAxisY)*2.0f);

		// Scale (mouse wheel)
		if (input.MouseAxis(MouseWheel)>0)
			plane->Scale(1.1f,1.1f);
		if (input.MouseAxis(MouseWheel)<0)
			plane->Scale(0.9f,0.9f);

		// Rotate (mouse buttons)
		if (input.MouseButton(MouseLeftButton))
			plane->Rotate(-10.0f);
		if (input.MouseButton(MouseRightButton))
			plane->Rotate(10.0f);

		// Fire (mouse middle button)
		if (input.MouseButton(MouseMiddleButton))
		{
			Restart();
		}
	}

	// ==== Xbox 360 Controller input ====
	if (xbox360On)
	{
		// Update joystick state
		input.GetXbox360State();
	
		// Vibration with trigger values
		input.Xbox360Vibrate(0, input.Xbox360Trigger(LTtrigger)*257, input.Xbox360Trigger(RTtrigger)*257);
			
		// Safe Stop Vibration
		if (input.Xbox360Button(BackButton))
			input.Xbox360Vibrate(0,0,0);

		// Start button resets
		if (input.Xbox360Button(StartButton))
		{	
			Restart();
		}

		// Translate (left analog stick)
		plane->Translate(input.Xbox360ThumbStick(LXthumb)/2000.0f, -1 * input.Xbox360ThumbStick(LYthumb)/2000.0f);
		
		// Translate with DPAD
		if (input.Xbox360Button(DpadUp))
			plane->Translate(0.0f, -10.0f);	// go up
		else if (input.Xbox360Button(DpadDown))
			plane->Translate(0.0f, 10.0f);	// go down

		if (input.Xbox360Button(DpadLeft))
			plane->Translate(-10.0f, 0.0f); // go left
		else if (input.Xbox360Button(DpadRight))
			plane->Translate(10.0f, 0.0f);	// go right

		// Scale (LB  and RB)
		if (input.Xbox360Button(LeftShoulder))
			plane->Scale(1.1f,1.1f);
		if (input.Xbox360Button(RightShoulder))
			plane->Scale(0.9f,0.9f);

		// Rotate (right analog stick)
		plane->Rotate(input.Xbox360ThumbStick(RXthumb)/5000.0f);
		plane->Rotate(input.Xbox360ThumbStick(RYthumb)/5000.0f);

		// Enable Bounding Box (A)
		if (input.Xbox360Button(Abutton))
			viewBB = true;

		// Disable Bounding Box (B)
		if (input.Xbox360Button(Bbutton))
			viewBB = false;

		// Enable Bounding Box (X)
		if (input.Xbox360Button(Xbutton))
			viewBB = true;

		// Disable Bounding Box (Y)
		if (input.Xbox360Button(Ybutton))
			viewBB = false;
	}
} 

/**********************************************************************************/

void CollisionDemo::GameDraw()
{
	bool collision = scene.CollisionDetection();

	if (!viewBB) circle->Draw();
		
	plane->Draw();

	if (!viewBB)
	{
		// test for collision
		if (collision)
		{
			planeRed->MoveTo(plane->x, plane->y);
			planeRed->scalingX = plane->scalingX;
			planeRed->scalingY = plane->scalingY;
			planeRed->rotation = plane->rotation;
			planeRed->Draw();
		}
	}

	/*******************************************************/

	// Draw the bounding boxes
	if (viewBB)
	{
		// Lock Screen for pixel plotting functions
		LockScreen();

		// test for collision
		if (collision)
		{
			// Draw bounding boxes
			circleBB->color = Color(255,40,70);
			planeBB->color = Color(255,40,70);

			circleBB->Draw();
			planeBB->Draw();
		}
		else
		{
			// Draw bounding boxes
			circleBB->color = Color(255,255,255);
			planeBB->color = Color(255,255,255);

			circleBB->Draw();
			planeBB->Draw();
		}

		UnLockScreen();
	}		

	/*******************************************************/

	demobox->Draw();
	demobar->Draw();

	sprintf_s(text, "Collision Demo");
	sysFont->Draw(55, 40, text);

	sprintf_s(text, "Sprite Collision Detection");
	sysFont->Draw(55, 80, text);

	sprintf_s(text, "<E> - Enable the bounding box");
	sysFont->Draw(55, 100, text);

	sprintf_s(text, "<D> - Disable the bounding box");
	sysFont->Draw(55, 120, text);
	
	sprintf_s(text, "<R> - Restart");
	sysFont->Draw(55, 140, text);

	sprintf_s(text, "<A> and <S> Scale   <Z> and <X> Rotate   <Arrows> Translate");
	sysFont->Draw(0, GetWindowHeight()-37.0f, text, Color(255,255,255), GetWindowWidth(), 30, DT_CENTER);

	if (xbox360On)
	{
		sprintf_s(text, "Xbox 360 Controller");
		sysFont->Draw(40, 200, text);	

		sprintf_s(text, "DPAD Up: %d", input.Xbox360Button(DpadUp));
		sysFont->Draw(40, 220, text);	
		sprintf_s(text, "DPAD Down: %d", input.Xbox360Button(DpadDown));
		sysFont->Draw(40, 240, text);
		sprintf_s(text, "DPAD Left: %d", input.Xbox360Button(DpadLeft));
		sysFont->Draw(40, 260, text);
		sprintf_s(text, "DPAD Right: %d", input.Xbox360Button(DpadRight));
		sysFont->Draw(40, 280, text);
		sprintf_s(text, "Start: %d", input.Xbox360Button(StartButton));
		sysFont->Draw(40, 300, text);
		sprintf_s(text, "Back: %d", input.Xbox360Button(BackButton));
		sysFont->Draw(40, 320, text);
		sprintf_s(text, "Left Thumb: %d", input.Xbox360Button(LeftThumb));
		sysFont->Draw(40, 340, text);
		sprintf_s(text, "Right Thumb: %d", input.Xbox360Button(RightThumb));
		sysFont->Draw(40, 360, text);
		sprintf_s(text, "LB Shoulder: %d", input.Xbox360Button(LeftShoulder));
		sysFont->Draw(40, 380, text);
		sprintf_s(text, "RB Shoulder: %d", input.Xbox360Button(RightShoulder));
		sysFont->Draw(40, 400, text);
		sprintf_s(text, "A Button: %d", input.Xbox360Button(Abutton));
		sysFont->Draw(40, 420, text);
		sprintf_s(text, "B Button: %d", input.Xbox360Button(Bbutton));
		sysFont->Draw(40, 440, text);
		sprintf_s(text, "X Button: %d", input.Xbox360Button(Xbutton));
		sysFont->Draw(40, 460, text);
		sprintf_s(text, "Y Button: %d", input.Xbox360Button(Ybutton));
		sysFont->Draw(40, 480, text);
		sprintf_s(text, "LT Trigger: %d", input.Xbox360Trigger(LTtrigger));
		sysFont->Draw(40, 500, text);
		sprintf_s(text, "RT Trigger: %d", input.Xbox360Trigger(RTtrigger));
		sysFont->Draw(40, 520, text);
		sprintf_s(text, "LX ThumbStick: %d", input.Xbox360ThumbStick(LXthumb));
		sysFont->Draw(40, 540, text);
		sprintf_s(text, "LY ThumbStick: %d", input.Xbox360ThumbStick(LYthumb));
		sysFont->Draw(40, 560, text);
		sprintf_s(text, "RX ThumbStick: %d", input.Xbox360ThumbStick(RXthumb));
		sysFont->Draw(40, 580, text);
		sprintf_s(text, "RY ThumbStick: %d", input.Xbox360ThumbStick(RYthumb));
		sysFont->Draw(40, 600, text);


	}	
} 



/**********************************************************************************/
/*                                  WinMain                                       */
/**********************************************************************************/

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	CollisionDemo coldemo;

	//coldemo.SetWindowMode(WINDOWED);
	//coldemo.SetWindowSize(1024,768);
	coldemo.SetWindowBgColor(10,25,55);
	coldemo.SetWindowTitle(string("Collision Demo"));
	coldemo.SetWindowIcon(LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)));
	coldemo.ShowWindowCursor(false);
	coldemo.Initialize(hInstance);
	coldemo.Start();
	
	return 0;

}

/**********************************************************************************/